import numpy as np
from matplotlib import pyplot as plt

# Show Chinese characters.
plt.rcParams['font.sans-serif'] = ['SimHei']
plt.rcParams['axes.unicode_minus'] = False

""" Fixed constants. """
A = 1050000  # Capital.
interest_rate = 0.049 / 12  # Interest rate.
inflation_rate = 0.0215  # Inflation rate.
premium_rate = 0.105  # Premium rate.
N = 10 * 12
k = 20
D = 3000


def get_dengebenjin(n):
    x = A / N + (1 - (n - 1) / N) * A * interest_rate
    return x


def get_dengebenxi(n):
    x = A * interest_rate * (1 + interest_rate)**N / \
        ((1 + interest_rate)**N - 1)
    return x


def get_dengedizeng(n):
    x = A / N + (n - (N + 1) / 2) * k + (A - (A / N - (N + 1) /
                                              2 * k) * n - k * n * (n + 1) / 2) * interest_rate
    return x


def get_dengeniandizeng(n):
    n = int((n - 1) / 12 + 1)
    rate = interest_rate * 12
    year = N / 12
    x = (rate**2*A-D*((1+rate)**year-rate*year-1)) / \
        (rate**2*year+rate*((1+rate)**year-rate*year-1))+A*rate+D*(n-1)
    return x / 12


def get_tax(sal, prem):
    tax = []
    should_total = 0
    tax_total = 0
    tax_rate = 0.03
    quick_deduction = 0
    should_month = sal - 5000 - 1000 - prem
    for i in range(1, 13):
        should_total += should_month
        if 144000 >= should_total > 36000:
            quick_deduction = 2520
            tax_rate = 0.1
        elif 300000 >= should_total > 144000:
            quick_deduction = 16920
            tax_rate = 0.2
        tax_month = should_total * tax_rate - quick_deduction - tax_total
        tax_total += tax_month
        tax.append(tax_month)
    return tax


""" Calculate (month) salary for each year. """
salary = [0, 12000]  # Monthly salary.
rise = 0.2  # Percentage of salary rise.
for i in range(2, 31):
    salary.append(salary[i - 1] * (1 + rise))
    rise *= (12000 / salary[-1])
# print(salary)

""" Calculate (month) living expenses every year. """
comfort = 3000  # To live comfortably.
survive = 2000  # To merely survive.
expense = [0]  # Average expense.
for i in range(1, 31):
    expense.append((comfort + survive) / 2)
    comfort *= 1 + inflation_rate
    survive *= 1 + inflation_rate
# print(expense)

""" Calculate (month) premium. """
premium = [0, 0]
for i in range(2, 31):
    premium.append(salary[i - 1] * premium_rate)
# print(premium)

""" Calculate taxes. """
tax = [0]
for i in range(1, 31):
    tax.extend(get_tax(salary[i], premium[i]))
# print(tax)

""" Calculate (month) balances. """
balance = [0]
total = [0]
for month in range(1, 361):
    year = int((month - 1) / 12 + 1)
    balance_now = salary[year] - premium[year] / \
        12 - tax[month] - expense[year]
    balance.append(balance_now)
    total.append(balance_now + total[month - 1])
# print(total)

mortgage_funcs = [get_dengebenjin, get_dengebenxi,
                  get_dengedizeng, get_dengeniandizeng]
mortgage_sorts = ['等额本金', '等额本息', '等额递增', '等额年递增']
total_list = []
""" Calculate deposit. """
for sort in range(4):
    temp = {}
    print('\n', mortgage_sorts[sort], '：\n')
    # print('年限\t  还款总额\n-------------------')
    N = 10 * 12
    for y in range(10, 31):
        total_money = 0
        deposit = 0
        for i in range(1, y * 12 + 1):
            deposit += balance[i] - mortgage_funcs[sort](i)
            total_money += mortgage_funcs[sort](i)
            if deposit < 0:
                print(f'选择{y}年期，则第{i}个月时，存款为负，舍去；')
                break
        else:
            print(f'选择{y}年期，还款总额为{round(total_money, 2)}元；')
            temp[y] = round(total_money, 2)
        N += 12
    total_list.append(temp)
# print(total_list)

""" Draw diagrams. """
# plt.title('四种方式的还款总额-年限图')
# plt.axis([10, 30, 1400000, 2300000])
# plt.xticks(list(range(10, 31)))
# plt.yticks(list(range(1400000, 2300001, 100000)), list(range(140, 231, 10)))
# plt.xlabel('年限（年）')
# plt.ylabel('还款总额（万元）')
# for i in range(4):
#     plt.plot(list(total_list[i].keys()), list(
#         total_list[i].values()), linestyle='-', label=mortgage_sorts[i])
# plt.legend()
# plt.grid()
# plt.show()
